# frozen_string_literal: true

class Shell
  alias raw_exit exit
  alias exe exec

  def exec(command)
    puts "+ #{command}" unless ENV['NO_SHELL_ECHO']
    success = system(command)
    exit Errors::SHELL_EXECUTION_ERROR, <<~END_SHELL_ERROR unless success

      [Shell 执行失败]
      命令：#{command}
      退出码：#{$?.exitstatus}
    END_SHELL_ERROR
  end

  def require(command)
    raise "未发现 #{command}，需要预先安装 #{command}" unless command?(command)
  end

  def command?(command)
    system "which #{command}", out: File::NULL, err: File::NULL
  end

  def expand(path)
    File.expand_path(path)
  end

  def rc_append(lines, rc_path = nil)
    lines = [lines] if lines.is_a?(String)
    rc_path = user_rc_path if rc_path.nil?

    text = "\n" + lines.join("\n") + "\n"
    File.write(expand(rc_path), text, mode: 'a')

    puts <<~RC_END
      已添加如下配置到 `#{rc_path}`：

      #{lines.map { |line| "    #{line}" }.join("\n")}
    RC_END
  end

  def user_rc_path
    case ENV['SHELL']
    when /zsh/
      '~/.zshrc'
    when /bash/
      '~/.bashrc'
    else
      raise "未知的 SHELL: #{ENV['SHELL']}"
    end
  end

  def exit(status, message)
    if status == 0
      puts message
      raw_exit
    else
      $stdout.puts message
      raw_exit status
    end
  end

  def sudo
    @_sudo_shell || @_sudo_shell = Shell::Sudo.new
  end

  alias execute exe

  module Errors
    COMMAND_NOT_FOUND = 201       # 一键脚本子命令不存在
    SHELL_EXECUTION_ERROR = 202   # Shell 命令执行失败，它的返回码非零
    FILE_NOT_FOUND = 203          # 文件未找到
    BACKUP_FILE_EXIST = 204       # 备份文件已存在
  end

  class Sudo
    def read(path)
      `sudo cat '#{path}'`
    end

    def write(path, content)
      shell.exec "echo '#{content}' | sudo tee '#{path}' > /dev/null"
    end

    def append(path, content)
      shell.exec "echo '#{content}' | sudo tee -a '#{path}' > /dev/null"
    end
  end
end

shell = Shell.new

define_method(:shell) { shell }
